#ifndef INTERFAZPEER_H_
#define INTERFAZPEER_H_


#include <string>
#include <queue>
#include "ThreadRecibidor.h"
#include "ThreadEnviador.h"
#include "Condition.h"
#include "ProtocoloPeer.h"
#include "Mutex.h"
#include "ThreadManejador.h"

class Conexion;
class ConexionPeer;
class Respuesta;
class Pieza;

class InterfazPeer
{
private:
	string server;
	unsigned long int puerto;

	unsigned long int cantidadPiezas;
	string peerId;

	ConexionPeer *conexion;
	ProtocoloPeer protocolo;

	ThreadRecibidor tRecibidor;
	ThreadEnviador tEnviador;

	ThreadManejador tManejador;

	queue<string> colaSalida;
	Condition conditionColaSalida;

	bool estoyChoking;
	Mutex mutexEstoyChoking;

	bool estoyInteresado;
	Mutex mutexEstoyInteresado;

	bool peerChoking;
	Mutex mutexPeerChoking;

	bool peerInteresado;
	Mutex mutexPeerInteresado;

	bool threadsArrancados;

	bool activo;
	Mutex mutexActivo;

	Condition *conditionError;

	Pieza* piezaActual;
	Mutex mutexPiezaActual;

	Condition conditionPeerChoking;
	Condition conditionTerminoBajado;

	Condition conditionColaEntrada;
	queue<Respuesta*> colaEntrada;

public:
	InterfazPeer(ConexionPeer *conexion, const string &peerId, unsigned long int cantidadPiezas, Condition *conditionError, Mutex *mutexPiezas, list<InformacionPieza*> *piezas, Mutex *mutexPiezasABajarOBajadas, list<unsigned long int> *piezasPorBajar, list<unsigned long int> *piezasBajadas, const string &server = "", const unsigned long int puerto = 0);
	virtual ~InterfazPeer();

	bool conectar(const string &server, const unsigned int puerto, const string &nombre);
	void desconectar();
	void mantenerVivo();
	void choke();
	void unchoke();
	void interesado();
	void noInteresado();
	bool tengo(const unsigned long int indicePieza);
	bool bitfield(const list<unsigned long int> &piezas);
	bool pedido(const unsigned long int indicePieza, const unsigned long int offsetPieza, const unsigned long int longitud);
	bool pieza(const unsigned long int indicePieza, const unsigned long int offsetPieza, const string &informacion);
	bool cancelar(const unsigned long int indicePieza, const unsigned long int offsetPieza, const unsigned long int longitud);

	string getServer() const;
	unsigned long int getPuerto() const;
	string getPeerId() const;

	bool getEstoyChoking();
	void setEstoyChoking(const bool estoyChoking);

	bool getEstoyInteresado();
	void setEstoyInteresado(const bool estoyInteresado);

	bool getPeerChoking();
	void setPeerChoking(const bool peerChoking);

	bool getPeerInteresado();
	void setPeerInteresado(const bool peerInteresado);

	bool getActivo();
	void setActivo(const bool activo);

	void enviarSenialNoActivo();

	Pieza* getPiezaActual();
	void setPiezaActual(Pieza* piezaActual);

	bool estaBajando();

private:
	void acolarParaSalida(const string &s);
	void shutdownAndClose(); //TODO ver de hacer private y usar en desconectar

};

#endif /* INTERFAZPEER_H_ */
